package com.authine.cloudpivot.ext.applicationservice;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.cola.dto.SingleResponse;
import com.authine.cloudpivot.ext.Enum.*;
import com.authine.cloudpivot.ext.constants.ModelConst;
import com.authine.cloudpivot.ext.constants.PlatformConst;
import com.authine.cloudpivot.ext.dto.Summary;
import com.authine.cloudpivot.ext.dto.base.PageList;
import com.authine.cloudpivot.ext.dto.finance.GoldenTaxUpdateModel;
import com.authine.cloudpivot.ext.dto.finance.TradeErpPoUpdate;
import com.authine.cloudpivot.ext.dto.model.invoice.InvoiceDetail;
import com.authine.cloudpivot.ext.dto.model.trade.OrderGoodsConvertTrade;
import com.authine.cloudpivot.ext.dto.model.trade.Trade;
import com.authine.cloudpivot.ext.dto.model.trade.UpdateTradeOrderStatus;
import com.authine.cloudpivot.ext.dto.query.FinanceReportQuery;
import com.authine.cloudpivot.ext.dto.query.TradeQuery;
import com.authine.cloudpivot.ext.dto.system.OrganizationDto;
import com.authine.cloudpivot.ext.dto.system.UserDto;
import com.authine.cloudpivot.ext.service.account.AccountService;
import com.authine.cloudpivot.ext.service.account.impl.AccountServiceImpl;
import com.authine.cloudpivot.ext.service.goldentax.GoldenTaxService;
import com.authine.cloudpivot.ext.service.goldentax.impl.GoldenTaxServiceImpl;
import com.authine.cloudpivot.ext.service.organiztion.OrganizationService;
import com.authine.cloudpivot.ext.service.settle.SettleService;
import com.authine.cloudpivot.ext.service.settle.impl.SettleServiceImpl;
import com.authine.cloudpivot.ext.service.trade.TradeService;
import com.authine.cloudpivot.ext.service.trade.impl.TradeServiceImpl;
import com.authine.cloudpivot.ext.utils.*;
import com.authine.cloudpivot.ext.utils.system.OrgInviteCodeUtils;
import com.authine.cloudpivot.ext.utils.system.ReportUtils;
import com.authine.cloudpivot.ext.utils.system.UserUtils;
import com.authine.hermes.app.launcher.service.ApplicationService;
import com.authine.mvp.app.launcher.domain.SelectorFormat;
import com.authine.mvp.app.launcher.domain.utills.ApplicationContextUtils;
import com.authine.mvp.app.launcher.dto.bo.response.BOList;
import com.authine.mvp.app.org.dto.domainmodel.UnitType;
import io.swagger.v3.oas.annotations.Operation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.assertj.core.util.Maps;
import org.gitlab4j.api.UserApi;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import javax.ws.rs.POST;
import javax.ws.rs.Path;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

import static com.authine.hermes.app.launcher.service.ApplicationServiceFoundation.CUSTOM_SERVICE;

@Path("TradeController")
@Slf4j
public class TradeController extends ApplicationService {
    public static OrganizationService organizationService = new OrganizationService();
    public static TradeService tradeService = new TradeServiceImpl();
    public static GoldenTaxService goldenTaxService = new GoldenTaxServiceImpl();
    public static SettleService settleService = new SettleServiceImpl();
    public static AccountService accountService = new AccountServiceImpl();

    @Path("listTrade")
    @POST
    @Operation(summary = "平台交易管理-交易表列表服务",description = "平台交易管理，客户交易管理，供应商交易管理,待申请开票查询时allowedInvoiceQuantityStart填0",tags = CUSTOM_SERVICE)
    public SingleResponse<BOList> listTrade(TradeQuery query) {
        BOList boList = new BOList();
        PageList<Trade> pageList = tradeService.listTradeByParam(query);
        if(pageList.getTotal()==0){
            return SingleResponse.of(boList);
        }
        List<Trade> tradeList = pageList.getData();
        processAlreadyInvoice(tradeList, InvoiceBusinessType.Product);
        processAlreadyMakeInvoice(tradeList, InvoiceBusinessType.Product);
        List<Map<String, Object>> datas = new ArrayList<>();
        tradeList.forEach(item -> {
                    Summary summery = item.getSummary();
                    StringBuffer sb = new StringBuffer(summery.getName())
                            .append("|").append(summery.getBrand())
                            .append("|").append(summery.getSpec())
                            .append("|").append(summery.getModel())
                            .append("|").append(summery.getUnit());
                    item.setUnit(summery.getUnit());
                    item.setAmountreceived(settleService.completedStatusSettle(item.getId()));
                    Map<String, Object> data = BeanUtil.beanToMap(item);
                    data.put("summary", sb.toString());
                    data.put("organization_id",Collections.singleton(item.getOrganization_id()));
                    data.put("platform_organization_id",Collections.singleton(item.getPlatform_organization_id()));
                    datas.add(data);
                });
        boList.setTotal(pageList.getTotal());
        boList.setData(datas);
        return SingleResponse.of(boList);
    }

    @Path("exportTrade")
    @POST
    @Operation(summary = "平台交易管理-交易结果导出", tags = CUSTOM_SERVICE)
    public SingleResponse exportTrade(TradeQuery query){
        //验证选择导出的报表类型是否正确
        Assert.notNull(query.getReportType(), "导出报表类型异常");
        Assert.notNull(query.getReportName(), "reportName不能为空");

        query.setPageSize(500).setPageIndex(1);
        PageList<Trade> tradePageList = tradeService.listTradeByParam(query);
        List<Map<String, Object>> fileData = new ArrayList<>();

        if(tradePageList.getTotal()>0){
            List<Trade> tradeList = tradePageList.getData();
            tradeList = processAlreadyInvoice(tradeList, InvoiceBusinessType.Product);
            tradeList = processAlreadyMakeInvoice(tradeList, InvoiceBusinessType.Product);
            fileData = tradeList.stream().map(trade->{
                Map<String, Object> map = new HashMap<>();
                map.put("id", trade.getId());
//            map.put("confirmOrganizationId", null);//
//            map.put("alreadySettleTotal", null); //todo
                map.put("typeName", TradeDirection.valueOf(trade.getDirection()).des);
                map.put("erpPo", trade.getErp_po());
                map.put("organizationName", trade.getOrganization_name());
                map.put("vendorOrderId", trade.getVendor_order_id());
                map.put("price", trade.getPrice()==null?0d:trade.getPrice().doubleValue());
                map.put("completedTotal", trade.getInvoiced()==null ? 0d : trade.getInvoiced().doubleValue());//已开票金额
                map.put("alreadyInvoiceTotal", trade.getAlready_invoice_total()==null?0d:trade.getAlready_invoice_total().doubleValue());
                map.put("alreadyMakeInvoiceTotal", settleService.completedStatusSettle(trade.getId()).doubleValue());//已收款金额
                map.put("quantity", trade.getQuantity());
                map.put("taxRate", trade.getTax_rate());
                map.put("orderGoodsId", trade.getOrder_goods_id());
                map.put("targetOrganizationName", trade.getTarget_organization_name());
                map.put("total", trade.getTotal());
                map.put("invoiceIds", trade.getInvoice_ids());
                map.put("time", trade.getCreatedTime());
                map.put("businessType", trade.getBusiness_type());
                map.put("customerOrderId", trade.getCustomer_order_id());
                map.put("summary", trade.getSummary());
                map.put("orderGoodsStatusDes", trade.getOrder_goods_status()==null ? "" : trade.getOrder_goods_status().des);
                return map;
            }).collect(Collectors.toList());
        }

        ReportUtils.exportReport(query.getReportName(), query.getReportType().getId(), fileData);
        return SingleResponse.buildSuccess();
    }
    /**
     * 通过订单生成交易记录
     * 订单模块调用
     * @return
     */
    @Path("createTrade")
    @POST
    @Operation(summary = "通过订单商品生成交易记录",description = "",tags = CUSTOM_SERVICE)
    public SingleResponse createTrade(Collection<OrderGoodsConvertTrade> orderGoodsParams){
        List<Trade> tradeList = new ArrayList<>();
        try{
            List<String> businessTypes = orderGoodsParams.stream().map(OrderGoodsConvertTrade::getBusinessType).distinct().collect(Collectors.toList());
            Assert.isTrue(businessTypes.size()==1, "订单类型不唯一");
            String businessType = businessTypes.get(0);

            List<Trade> purchaseTradeList = orderGoodsParams.stream().map(OrderGoodsConvertTrade::convertToPurchaseTrade).collect(Collectors.toList());
            List<Trade> saleTradeList = orderGoodsParams.stream().map(OrderGoodsConvertTrade::convertToSaleTrade).collect(Collectors.toList());
            tradeList.addAll(purchaseTradeList);
            tradeList.addAll(saleTradeList);
            //Ordinary=普通订单
            if(businessType.equals("Ordinary")){
                setPropertyForOrdinaryTrade(saleTradeList, purchaseTradeList);
            }else{
                setActualAccountPeriod(tradeList);
            }

            //验证参数合法性
            createVerify(tradeList);
            //持久化交易
            BoServiceUtils.createBo(ModelConst.T_TRADE, tradeList.stream().map(Trade::beanToMap).collect(Collectors.toList()));
            //更新账户  todo 防止订单支付创建交易报错，暂时注释
            accountService.saveByTrades(tradeList);
        }catch (Exception e){
            log.error("订单创建交易失败",e);
            return SingleResponse.buildFailure("-1", e.getMessage());
        }
        return SingleResponse.buildSuccess();
    }

    public void setPropertyForOrdinaryTrade(List<Trade> saleTradeList, List<Trade> purchaseTradeList){
        //验证采购客户的结算组织是否唯一
        Set<String> customerOrgIds = saleTradeList.stream().map(item -> item.getOrganization_id().getId()).collect(Collectors.toSet());
        List<OrganizationDto> organizationDtos = organizationService.getOrganizationByIds(customerOrgIds);
        List<SelectorFormat> transOrgs = organizationDtos.stream().filter(item->!CollectionUtils.isEmpty(item.getTransaction_organization_id()))
                .map(item->item.getTransaction_organization_id().get(0)).distinct().collect(Collectors.toList());
        Assert.isTrue(transOrgs.size()==1, "客户结算组织异常");

        //供应商组织ID
        List<String> vendorOrgIds = purchaseTradeList.stream().map(t->t.getOrganization_id().getId()).collect(Collectors.toList());
        //客户的结算组织ID
        String customerTransactionOrgId = transOrgs.get(0).getId();
        //供应商对应的平台费率
        Map<String, BigDecimal> platformRateMap = OrgInviteCodeUtils.listPlatformRate(customerTransactionOrgId, vendorOrgIds);

        //设置销售交易的相关属性
        saleTradeList.stream().collect(Collectors.groupingBy(Trade::getOrganization_id)).forEach((organiztion, values)->{
            OrganizationDto organizationDto = organizationService.getOrganizationById(organiztion.getId());
            //获取对应平台组织ID
            Assert.notNull(organizationDto, "未获取到客户组织");
            Assert.notNull(organizationDto.getPlatform_id(), "未获取到客户对应平台组织ID");
            Assert.notNull(organizationDto.getPlatform_name(), "未获取到客户对应平台组织名称");
            for (Trade trade : values) {
                trade.setPlatform_organization_id(organizationDto.getPlatform_id().get(0))  //交易对应平台组织
                        .setPlatform_organization_name(organizationDto.getPlatform_name())  //平台组织名称
                        .setActual_account_period(organizationDto.getStatement_cycle().toString()) // 客户真实账期
                        .getExtends_attr().setSettlementStrategy(organizationDto.getPayment_day_strategy()); //开票后多少天结算
            }
        });
        //设置采购交易的相关属性
        purchaseTradeList.stream().collect(Collectors.groupingBy(Trade::getOrganization_id)).forEach((organization, values)->{
            OrganizationDto organizationDto = organizationService.getOrganizationById(organization.getId());
            //判断是否是小规模供应商
            boolean smallScale = null != organizationDto.getSmall_scale() ? organizationDto.getSmall_scale() : false;
            //小规模供应商平台服务费率
            BigDecimal smallScaleRate = BigDecimal.ZERO;
            if (smallScale) {
                Assert.notNull(organizationDto.getSmall_scale_rate(), "维护小规模服务费率");
                smallScaleRate = organizationDto.getSmall_scale_rate();
            }

            for (Trade trade : values) {
                List<Trade> mappingList = saleTradeList.stream().filter(t -> t.getTarget_order_goods_id().equals(trade.getOrder_goods_id())).distinct().collect(Collectors.toList());
                Assert.isTrue(!CollectionUtils.isEmpty(mappingList) && mappingList.size() == 1, "采购交易获取对应销售交易异常");

                trade.setPlatform_organization_id(mappingList.get(0).getPlatform_organization_id());
                trade.setPlatform_organization_name(mappingList.get(0).getPlatform_organization_name());
                trade.setActual_account_period(organizationDto.getStatement_cycle() == null ? null: organizationDto.getStatement_cycle().toString()); //真实账期
                trade.getExtends_attr().setSettlementStrategy(organizationDto.getPayment_day_strategy()); //开票后多少天结算
                //采购交易对应的平台费率
                BigDecimal plateRate = BigDecimalUtils.add(platformRateMap.get(trade.getOrganization_id().getId()), smallScaleRate);
                trade.setPlatform_rate(plateRate);
            }
        });
    }

    /**
     * 设置交易的真实账期
     * @param trades
     */
    public void setActualAccountPeriod(List<Trade> trades){
        List<String> orgIds = trades.stream().map(t->t.getOrganization_id().getId()).collect(Collectors.toList());
        List<OrganizationDto> orgList = organizationService.getOrganizationByIds(orgIds);
        for (Trade trade : trades){
            List<OrganizationDto> collect = orgList.stream().filter(t -> trade.getOrganization_id().getId().equals(t.getId())).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(collect)) {
                trade.setActual_account_period(collect.get(0).getStatement_cycle()+"");
            }
        }
    }

    /**
     * 如果订单走转采，回写交易转采标识
     * 订单模块调用
     * @return
     */
    @Path("writeBackTransfer")
    @POST
    @Operation(summary = "回写交易的转采标识",description = "",tags = CUSTOM_SERVICE)
    public SingleResponse writeBackTransfer(Collection<String> orderGoodsIds){
        SingleResponse<BOList> trades = BoServiceUtils.findListByIn(ModelConst.T_TRADE, "order_goods_id", orderGoodsIds);
        List<Map<String, Object>> data = trades.getData().getData();
        data.forEach(item->{
            item.put("transfer_purchase", true);
            BoServiceUtils.updateMainBo(ModelConst.T_TRADE,item);
        });
        return SingleResponse.buildSuccess();
    }

    /**
     * 订单维护金税编码后，回写对应交易的金税编码
     * 订单模块调用
     * @return
     */
    @Path("writeBackGoldenTax")
    @POST
    @Operation(summary = "回写对应交易的金税编码",description = "",tags = CUSTOM_SERVICE)
    public SingleResponse writeBackGoldenTax(Collection<GoldenTaxUpdateModel> models){
        List<String> orderGoodsIds = models.stream().map(GoldenTaxUpdateModel::getOrderGoodsId).collect(Collectors.toList());
        List<Trade> tradeList = JdbcTemplateUtils.builder(ModelConst.T_TRADE).selectField("*")
                .in("order_goods_id", orderGoodsIds)
                .queryForPOJOList(Trade.class);
        List<InvoiceDetail> tradeIdAndGoldenTaxParam = new ArrayList<>();
        //更新交易上面的金税编码
        for (Trade trade : tradeList){
            GoldenTaxUpdateModel updateModel = models.stream().filter(t -> t.getOrderGoodsId().equals(trade.getOrder_goods_id())).findFirst().get();
            Map<String, Object> param = Maps.newHashMap("id", trade.getId());
            param.put("golden_tax", updateModel.getGoldenTax());
            BoServiceUtils.updateMainBo(ModelConst.T_TRADE, param);
            if (trade.getDirection().equals(TradeDirection.Sale.name())){
                tradeIdAndGoldenTaxParam.add(InvoiceDetail.builder().trade_id(trade.getId()).golden_tax(updateModel.getGoldenTax()).build());
            }
        }
        //更新发票明细上面的金税编码
        if(!CollectionUtils.isEmpty(tradeIdAndGoldenTaxParam)){
            //金税开票表更新信息
            Collection<GoldenTaxUpdateModel> writeBackGoldenTaxInvoice = new ArrayList<>();
            List<InvoiceDetail> invoiceDetailList = JdbcTemplateUtils.builder(ModelConst.T_INVOICE_DETAIL).selectField("*")
                    .in("trade_id",tradeIdAndGoldenTaxParam.stream().map(InvoiceDetail::getTrade_id).collect(Collectors.toList()))
                    .queryForPOJOList(InvoiceDetail.class);
            if(invoiceDetailList.size()>0) {
                for (InvoiceDetail invoiceDetail : invoiceDetailList) {
                    InvoiceDetail update = tradeIdAndGoldenTaxParam.stream().filter(t -> t.getTrade_id().equals(invoiceDetail.getTrade_id())).findAny().get();
                    Map<String, Object> param = Maps.newHashMap("id", invoiceDetail.getId());
                    param.put("golden_tax", update.getGolden_tax());
                    BoServiceUtils.updateMainBo(ModelConst.T_INVOICE_DETAIL, param);

                    String golden_tax_id = JdbcTemplateUtils.builder(ModelConst.T_INVOICE_APPLY).selectField("golden_tax_id")
                            .eq("id", invoiceDetail.getInvoice_apply_id())
                            .queryForObject(String.class);
                    writeBackGoldenTaxInvoice.add(GoldenTaxUpdateModel.builder()
                            .goldenTaxId(golden_tax_id)
                            .goldenTax(update.getGolden_tax())
                            .oldGoldenTax(invoiceDetail.getGolden_tax())
                            .name(invoiceDetail.getName())
                            .modelSpec(invoiceDetail.getModel_spec())
                            .unit(invoiceDetail.getUnit())
                            .quantity(invoiceDetail.getQuantity())
                            .grossPrice(invoiceDetail.getGross_price())
                            .ifUpdate(false)
                            .build());

                }
                goldenTaxService.updateGoldenTax(writeBackGoldenTaxInvoice);
            }
        }


        return SingleResponse.buildSuccess();
    }

    /**
     * 回写交易对应的ERP_PO号
     * 订单模块调用
     * @return
     */
    @Path("writeBackErpPo")
    @POST
    @Operation(summary = "回写交易对应的ERP_PO号",description = "",tags = CUSTOM_SERVICE)
    public SingleResponse writeBackErpPo(Collection<TradeErpPoUpdate> tradeErpPoUpdate){
        if(CollectionUtils.isEmpty(tradeErpPoUpdate)){
            return SingleResponse.buildFailure("-1", "参数为空");
        }
        List<String> customerOrderIds = tradeErpPoUpdate.stream().map(TradeErpPoUpdate::getCustomerOrderId).collect(Collectors.toList());
        if(CollectionUtils.isEmpty(customerOrderIds)){
            return SingleResponse.buildFailure("-1", "订单商品ID为空");
        }
        List<Trade> tradeList = JdbcTemplateUtils.builder(ModelConst.T_TRADE).selectField("*")
                .in("customer_order_id", customerOrderIds)
                .queryForPOJOList(Trade.class);
        for (Trade trade : tradeList){
            TradeErpPoUpdate erpPoUpdate = tradeErpPoUpdate.stream().filter(t->t.getCustomerOrderId().equals(trade.getCustomer_order_id())).collect(Collectors.toList()).get(0);
            Map<String, Object> param = Maps.newHashMap("id",trade.getId());
            param.put("erp_po", erpPoUpdate.getErpPo());
            BoServiceUtils.updateMainBo(ModelConst.T_TRADE, param);
        }
        return  SingleResponse.buildSuccess();
    }

    /**
     * 回写订单对应交易的订单商品状态
     * 订单模块调用
     * @return
     */
    @Path("writeBackTradesOrder")
    @POST
    @Operation(summary = "回写订单对应交易的订单商品状态", description = "",tags = CUSTOM_SERVICE)
    public SingleResponse writeBackTradesOrder(Collection<UpdateTradeOrderStatus> params){
        if(CollectionUtils.isEmpty(params)){
            return SingleResponse.buildFailure("-1", "参数为空");
        }
        Collection<String> orderGoodsIds = params.stream().map(t->t.getOrderGoodsId()).collect(Collectors.toList());
        if(CollectionUtils.isEmpty(orderGoodsIds)){
            return SingleResponse.buildFailure("-1", "订单商品编号为空");
        }
        //销售
        List<Trade> saleTradeList = JdbcTemplateUtils.builder(ModelConst.T_TRADE).selectField("*")
                .in("order_goods_id", orderGoodsIds)
                .queryForPOJOList(Trade.class);
        //采购
        List<Trade> purchaseTradeList = JdbcTemplateUtils.builder(ModelConst.T_TRADE).selectField("*")
                .in("target_order_goods_id", orderGoodsIds)
                .queryForPOJOList(Trade.class);
        for (Trade trade : saleTradeList){
            UpdateTradeOrderStatus update = params.stream().filter(t->t.getOrderGoodsId().equals(trade.getOrder_goods_id())).collect(Collectors.toList()).get(0);
            Map<String, Object> param = Maps.newHashMap("id",trade.getId());
            param.put("order_goods_status", update.getOrderGoodsStatus());
            param.put("order_goods_returns_status", update.getOrderGoodsReturnsStatus());
            BoServiceUtils.updateMainBo(ModelConst.T_TRADE, param);
        }
        for (Trade trade : purchaseTradeList){
            UpdateTradeOrderStatus update = params.stream().filter(t->t.getOrderGoodsId().equals(trade.getTarget_order_goods_id())).collect(Collectors.toList()).get(0);
            Map<String, Object> param = Maps.newHashMap("id",trade.getId());
            param.put("order_goods_status", update.getOrderGoodsStatus());
            param.put("order_goods_returns_status", update.getOrderGoodsReturnsStatus());
            BoServiceUtils.updateMainBo(ModelConst.T_TRADE, param);
        }
        return SingleResponse.buildSuccess();
    }


    /**
     * 获取已申票金额和数量
     * @param tradeList 交易记录
     * @param business_type 业务类型
     * @return
     */
    public List<Trade> processAlreadyInvoice(List<Trade> tradeList, InvoiceBusinessType business_type){
        if (CollectionUtils.isEmpty(tradeList)) {
            return tradeList;
        }

        List<String> tradeIds = tradeList.stream().map(Trade::getId).collect(Collectors.toList());
        if(CollectionUtils.isEmpty(tradeIds)) {
            return tradeList;
        }
        StringBuffer sql = new StringBuffer("select d.trade_id, SUM(d.quantity-d.offset_quantity) as quantity,SUM(d.total-d.offset_total) as total  ")
                .append(" from i_financialcenter_t_invoice_detail d LEFT JOIN i_financialcenter_t_invoice_apply a on d.invoice_apply_id = a.id")
                .append(" where d.trade_id in (:tradeIds) ")
                .append(" and a.business_type = :business_type")
                .append(" group by  d.trade_id");
        Map<String, Object> param = new HashMap<>();
        param.put("tradeIds", tradeIds);
        param.put("business_type", business_type.name());
        List<InvoiceDetail> alreadyInvoice = JdbcTemplateUtils.queryForPOJOList(sql.toString(), param, ModelConst.T_INVOICE_DETAIL, InvoiceDetail.class);
        tradeList.forEach(trade ->{
            if (!CollectionUtils.isEmpty(alreadyInvoice)) {
                List<InvoiceDetail> invoiceDetailList = alreadyInvoice.stream().filter(t -> trade.getId().equals(t.getTrade_id())).collect(Collectors.toList());
                trade.setAlready_invoice_quantity(CalculatorUtils.sum(invoiceDetailList, BiFunctionConst.invoiceDetailQuantityFun));
                trade.setAlready_invoice_total(CalculatorUtils.sum(invoiceDetailList, BiFunctionConst.invoiceDetailTotalFun));
            }else{
                trade.setAlready_invoice_quantity(BigDecimal.ZERO);
                trade.setAlready_invoice_total(BigDecimal.ZERO);
            }

        });

        return tradeList;

    }

    /**
     * 获取已开票金额和数量
     * @param tradeList 交易记录
     * @param businessType 业务类型
     * @return 赋值后的list
     */
    private List<Trade> processAlreadyMakeInvoice(List<Trade> tradeList, InvoiceBusinessType businessType){
        if(CollectionUtils.isEmpty(tradeList)){
            return tradeList;
        }

        List<String> tradeIds = tradeList.stream().map(Trade::getId).collect(Collectors.toList());
        if(CollectionUtils.isEmpty(tradeIds)) {
            return tradeList;
        }
        StringBuffer sql = new StringBuffer("select d.trade_id, SUM(d.quantity-d.offset_quantity) as quantity,SUM(d.total-d.offset_total) as total  ")
                .append(" from i_financialcenter_t_invoice_detail d LEFT JOIN i_financialcenter_t_invoice_apply a on d.invoice_apply_id = a.id")
                .append(" where d.deleted = 0 and d.trade_id in (:tradeIds) ")
                .append(" and a.business_type = :business_type")
                .append(" and a.statuss = :status")
                .append(" group by  d.trade_id");
        Map<String, Object> param = new HashMap<>();
        param.put("tradeIds", tradeIds);
        param.put("business_type", businessType.name());
        param.put("status", InvoiceStatus.Done.name());
        List<InvoiceDetail> alreadyMakeInvoice = JdbcTemplateUtils.queryForPOJOList(sql.toString(), param, ModelConst.T_INVOICE_DETAIL, InvoiceDetail.class);
        tradeList.forEach(trade ->{
            BigDecimal quantity = BigDecimal.ZERO, total = BigDecimal.ZERO;
            if (!CollectionUtils.isEmpty(alreadyMakeInvoice)) {
                List<InvoiceDetail> invoiceDetailList = alreadyMakeInvoice.stream().filter(t -> trade.getId().equals(t.getTrade_id())).collect(Collectors.toList());
//                quantity = CalculatorUtils.sum(invoiceDetailList, BiFunctionConst.invoiceDetailQuantityFun);
                total = CalculatorUtils.sum(invoiceDetailList, BiFunctionConst.invoiceDetailTotalFun);
            }
            trade.setInvoiced(total);
//            trade.setAlready_invoice_total(total);
        });
        return tradeList;
    }

    /**
     * 验证交易创建参数的合法性
     * @param trades 交易记录
     */
    private void createVerify(List<Trade> trades){
        for (Trade trade : trades) {
            Assert.notNull(trade.getOrder_goods_id(), "订单商品编号不能为空");
            Assert.notNull(trade.getDirection(), "业务方向不能为空");
            Assert.notNull(trade.getBusiness_type(), "业务类型不能为空");
            Assert.notNull(trade.getOrganization_id(), "组织ID不能为空");
            Assert.notNull(trade.getOrganization_name(), "组织名称不能为空");
            Assert.notNull(trade.getQuantity(), "数量不能为空");
            Assert.notNull(trade.getPrice(), "单价不能为空");
            Assert.notNull(trade.getTotal(), "金额不能为空");
            Assert.notNull(trade.getTax_rate(), "税率不能为空");

            Summary summary = trade.getSummary();
            Assert.notNull(summary, "交易摘要不能为空");
            Assert.notNull(summary.getName(), "订单商品品名不能为空");
            Assert.notNull(summary.getBrand(), "订单商品品牌不能为空");
            Assert.notNull(summary.getSpec(), "订单商品规格不能为空");
            Assert.notNull(summary.getModel(), "订单商品型号不能为空");
            Assert.notNull(summary.getUnit(), "订单商品单位不能为空");

            //金额验证
            BigDecimal verifyTotal = trade.getQuantity().multiply(trade.getPrice()).setScale(2, RoundingMode.CEILING);
            if (verifyTotal.compareTo(trade.getTotal()) != 0) {
                throw new IllegalArgumentException("金额不等于数量x单价");
            }

            if (trade.getPlatform_organization_id() == null) {
                trade.setPlatform_organization_id(Utils.createSelecorFormat(PlatformConst.ORGANIZATION_ID, PlatformConst.ORGANIZATION_NAME, UnitType.DEPARTMENT.getIndex()));
            }
            if (StringUtils.isBlank(trade.getPlatform_organization_name())) {
                trade.setPlatform_organization_name(PlatformConst.ORGANIZATION_NAME);
            }
        }
        List<String> orderGoodsIds = trades.stream().map(Trade::getOrder_goods_id).collect(Collectors.toList());
        List<String> directions = trades.stream().map(Trade::getDirection).collect(Collectors.toList());
        List<String> businessTypes = trades.stream().map(Trade::getBusiness_type).collect(Collectors.toList());
        Integer count = JdbcTemplateUtils.builder(ModelConst.T_TRADE).selectField(" count(id) ")
                .in("order_goods_id", orderGoodsIds)
                .in("direction", directions)
                .in("business_type", businessTypes)
                .queryForObject(Integer.class);
        Assert.isTrue(count==0, "该商品已存在交易");

    }


}
